#ifndef RENDERWINDOW_H
#define RENDERWINDOW_H

#include "ClickManager.h"
#include "PDBManager.h"
#include "Matt/Vector.h"

// Contains cached residue drawing information.
struct ResidueDrawingInfo;

// Cached opengl data shared by all RenderWindows sharing a PDBManager object.
// Note that currently different RenderWindows sharing a PDBManager never draw
// the same chains, but may change that.
// Uses reference counting.  Pointer passed on creation, allocates as needed.
struct RenderData;

class RenderWindow : public ClickManager<wxGLCanvas> {
protected:
	RenderData *renderData;
	int lastModel;
	int lastChain;
	int lastResidue;
	int labelChain;

	// scale factor based on window size
	double windowScale;

	// Only used for drawing box while selecting by dragging.
	// Rest is handled by click manager.
	int dragging;

	static RenderWindow *lastDrawn;
	static int renderWindowCount;
	static int needContextInit;

	int width, height;
	PDBManager *pdbManager;
	MainWindow *mainWindow;
	int restrictChain;

	void InitContext();
	void UpdateViewport(int selecting=0, double x=0, double y=0, int w=0, int h=0);
	void CleanupLists();
	void DrawScene(int selecting=0, double x=0, double y=0, int w=0, int h=0);
	ResidueIndex *GetObjects(int x1, int y1, int x2, int y2);
	int GetObject(int x, int y, int *out);

	void KeepCurrentRotation();

	void SelectClickedResidue(int x, int y);

	void MultipleClick(int clickCount);
	void DragDone(int cancelled);
	void UpdateDragSel(int startx, int starty, int lastx, int lasty);

	void ArcBall(int startx, int starty, int lastx, int lasty, int smooth);
	void Translate(int startx, int starty, int lastx, int lasty);
	void Zoom(int starty, int lasty);
	void CaptureLost();

	// Removes and elements of the undo buffer that match
	// the current transformation.  Must be used before
	// actually calling undo on PDBManager.
	void CheckUndoBuffer();

	void DXDY(int startx, int starty, int lastx, int lasty);
	void CalcFullCurrentRotation(Matrix *out);

	Transform *GetCurrentTransform();

	ResidueDrawingInfo *residueDrawingInfo;
public:
	void UpdatePDB(PDBManager *pdbManager, int restrictChain, int labelChain, RenderData **renderData);

	void CenterCamera(int frame);

	// Colors and graphics setting may have been changed.
	// Called first on all windows.  Cleans up old data.
	void ConfigChangedUninit();
	// Called next on all Windows.  Allocates new data.
	// As data is shared, needed to prevent redundant calculations.
	void ConfigChangedInit();

	void DoNothing(wxEraseEvent& evt);
	RenderWindow(wxWindow *parent, MainWindow *mainWindow, PDBManager* pdbManager, int restrictChain=-1, int labelChain = 0);
	~RenderWindow();
	void OnSize(wxSizeEvent& evt);
	void render(wxPaintEvent& evt);

	int GetClickedResidue(int x, int y, int *model, int *chain, int *residue);
	void MouseMove(unsigned int flags, int x, int y);
	void MouseDown(unsigned int button, int clickCount, unsigned int flags, int x, int y);
	//void MouseMove(unsigned int flags, int x, int y);
	void MouseDrag(unsigned int flags, int xStart, int yStart, int xStop, int yStop);
	// Also called on key up.
	void MouseUp(unsigned int button, int clickCount, unsigned int flags, int x, int y);
	void MouseWheel(unsigned int wheel, int delta, unsigned int flags, int lastActionWasWheel);

	void ResetZoom(int redraw);
	void ResetOrientation(int redraw);
	void ResetCamera(int redraw);

	// Even though I've both set EVT_ERASE_BACKGROUND to do nothing and set bg mode to
	// wxBG_STYLE_CUSTOM, calling refresh with erase background = 1 destroys performance
	// on windows (Redrawing takes at least 5 times longer).  Overriding this fixes the problem.
	// Note that eraseBackground parameter is completely ignored.
	// Not sure if this is an issue with wxWidgets or the Window API.
    void Refresh(bool eraseBackground = false, const wxRect *rect = (const wxRect *) NULL);

	// Note:  Only redraws the render window.
	void ForceRedraw(int all=0);

	DECLARE_EVENT_TABLE()
};

#endif
